﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
using log4net.Repository.Hierarchy;
using log4net.Appender;
using log4net.Layout;
using System.Reflection;
using System.Web;
using System.IO;
using System.Collections;

namespace Framework.Common
{
    public static class LogHelper
    {
        static ILog Instance { get; set; }
        static LogHelper()
        {
            string configFile = PathHelper.MapPath("log4net.config");
            if (FileHelper.FileExists(configFile))
            {
                log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(configFile));
                Instance = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
            }
            else
            {
                string LOG_PATTERN = "%d [%t] %-5p %c [%x] - %m%n";
                string LOG_FILE_PATH = PathHelper.MapPath("~/Log/log.txt");

                Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();
                hierarchy.Name = "framework.log";
                TraceAppender tracer = new TraceAppender();

                PatternLayout patternLayout = new PatternLayout();
                patternLayout.ConversionPattern = LOG_PATTERN;
                patternLayout.ActivateOptions();

                tracer.Layout = patternLayout;
                tracer.ActivateOptions();
                hierarchy.Root.AddAppender(tracer);

                RollingFileAppender roller = new RollingFileAppender();
                roller.Layout = patternLayout;
                roller.AppendToFile = true;
                roller.RollingStyle = RollingFileAppender.RollingMode.Date;
                roller.MaxSizeRollBackups = 4;
                roller.MaximumFileSize = "1000KB";
                roller.StaticLogFileName = true;
                roller.File = LOG_FILE_PATH;
                roller.ActivateOptions();

                hierarchy.Root.AddAppender(roller);
                hierarchy.Root.Level = log4net.Core.Level.All;
                hierarchy.Configured = true;

                Instance = log4net.LogManager.GetLogger("framework.log");
            }
        }
        #region standard method
        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        public static void Debug(object message)
        {
            Instance.Debug(message);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        public static void Debug(object message, Exception exception)
        {
            Instance.Debug(message, exception);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        public static void Error(object message)
        {
            Instance.Error(message);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        public static void Error(object message, Exception exception)
        {
            Instance.Error(message, exception);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        public static void Fatal(object message)
        {
            Instance.Fatal(message);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        public static void Fatal(object message, Exception exception)
        {
            Instance.Fatal(message, exception);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        public static void Info(object message)
        {
            Instance.Info(message);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        public static void Info(object message, Exception exception)
        {
            Instance.Info(message, exception);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        public static void Warn(object message)
        {
            Instance.Warn(message);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        public static void Warn(object message, Exception exception)
        {
            Instance.Warn(message, exception);
        }
        #endregion

        /// <summary>
        /// record web errors log
        /// </summary>
        /// <param name="ex"></param>
        public static void WriteWebErrorDetail(Exception ex)
        {
            var httpEx = ex as HttpException;
            if (httpEx != null && (httpEx.ErrorCode == 404 || httpEx.ErrorCode == 403))
            {
                return;
            }
            var rq = HttpContext.Current.Request;
            StringBuilder sbError = new StringBuilder();
            sbError.AppendLine("error title is :" + ex.Message);
            sbError.AppendLine("Request Url is :" + rq.Url);
            sbError.AppendLine("Request UrlReferrer is :" + rq.UrlReferrer);
            sbError.AppendLine("------------Request QueryString is :------------");
            foreach (var key in rq.QueryString.AllKeys)
            {
                sbError.AppendLine(key + "=" + rq.QueryString[key]);
            }
            sbError.AppendLine("------------Request Forms is :------------------");
            foreach (var key in rq.Form.AllKeys)
            {
                sbError.AppendLine(key + "=" + rq.QueryString[key]);
            }
            Fatal(sbError.ToString(), ex);
        }

        /// <summary>
        /// Dump To Json Format/PlainText
        /// </summary>
        /// <param name="obj"></param>
        public static void Dump(Object obj, DumpType dumpType = DumpType.JsonFormat)
        {
            StringBuilder dumpString = new StringBuilder();
            if (obj == null)
            {
                dumpString.Append("Dumped Object Is Null");
            }
            else
            {
                dumpString.AppendLine(obj.GetType().FullName);
                dumpString.AppendLine();
                string dumpInfo = string.Empty;
                switch (dumpType)
                {
                    case DumpType.JsonFormat:
                        dumpInfo = new Serializer.JsonSerializeHelper().Serialize(obj);
                        break;
                    case DumpType.ObjectDumpFormat:
                        dumpInfo = ObjectDumperHelper.Write(obj, 4).ToString();
                        break;
                }
                dumpString.AppendLine(dumpInfo);
                dumpString.AppendLine();
            }
            Instance.Debug(dumpString);
        }

        public enum DumpType
        {
            JsonFormat,
            ObjectDumpFormat
        }
    }
}
